package com.example.qihuibao.utils

import com.example.qihuibao.XApplication
import com.example.qihuibao.bean.DeviceBean
import com.example.qihuibao.constant.Config
import com.github.gzuliyujiang.oaid.DeviceID
import com.google.gson.Gson
import java.net.*


object ConnectUtil {
    //广播
    private const val IP = "255.255.255.255"//貌似路由器会丢掉这些数据包？
    private const val PORT = 65500
    private const val UDPBroadcastMessage = "i am server"

    fun sendUDPBroadcast() {
        val msg: ByteArray = UDPBroadcastMessage.toByteArray()
         //在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如：这里使用了本地的广播地址
        val inetAddr = InetAddress.getByName(IP)
        val client = DatagramSocket()
        client.send(DatagramPacket(msg, msg.size, inetAddr, PORT))
        client.disconnect()
        client.close()
    }

    fun receiveUDPBroadcast(receive:(message:String, ip:String)->Unit) {
        if (!Config.isStation) {
            val len = 1024
            val byteArray = ByteArray(len)
            val socket = DatagramSocket(PORT)
            val packet = DatagramPacket(byteArray, len)
            socket.receive(packet)
            val message = String(byteArray)
            val hostIp = packet.address.hostAddress
            receive(message, hostIp)
            socket.disconnect()
            socket.close()
            //返回给server
            val deviceBean = DeviceBean("${DeviceID.getAndroidID(XApplication.application)}", hostIp)
            val msg: ByteArray = "${Gson().toJson(deviceBean)}".toByteArray()
            //在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如：这里使用了本地的广播地址
            val inetAddr = InetAddress.getByName(hostIp)
            val datagramPacket = DatagramSocket()
            datagramPacket.send(DatagramPacket(msg, msg.size, inetAddr, PORT+1))
            datagramPacket.disconnect()
            datagramPacket.close()
        }else {
            val len = 1024
            val byteArray = ByteArray(len)
            val socket = DatagramSocket(PORT+1)
            val packet = DatagramPacket(byteArray, len)
            socket.receive(packet)
            val message = String(byteArray)
            val hostIp = packet.address.hostAddress
            receive(message, hostIp)
            socket.disconnect()
            socket.close()
        }
    }

    //组播(UDP)
    const val GROUP_PORT = 18611
    const val GROUP_IP = "239.0.0.3"//239.0.0.0～239.255.255.255为本地管理组播地址

    //发送组播
    fun groupSend(targetIp:String = "", message:String = "") {
        if (IpUtil.getHostIP().isEmpty()) return
        Thread {
            try {
                val deviceBean = DeviceBean(DeviceID.getAndroidID(XApplication.application), IpUtil.getHostIP(), Config.isStation, targetIp, message)
                val sendBuffer = Gson().toJson(deviceBean).toByteArray()
                val multicastSocket = MulticastSocket(GROUP_PORT)
                val inetAddress = InetAddress.getByName(GROUP_IP)
                multicastSocket.joinGroup(inetAddress)
                multicastSocket.soTimeout = 5000
                val sendPacket = DatagramPacket(sendBuffer, sendBuffer.size, inetAddress, GROUP_PORT)
//            LogUtil.e("ip$GROUP_IP:$GROUP_PORT byte$sendBuffer")
                multicastSocket.send(sendPacket)
                multicastSocket.close()
            }catch (e:Exception) {
                LogUtil.e("groupSend error:${e.message}")
            }
        }.start()
    }

    //接收组播
    fun groupReceive(back:(message:String?)->Unit) {
        if (IpUtil.getHostIP().isEmpty()) return
        try {
            val multicastSocket = MulticastSocket(GROUP_PORT)
            val inetAddress = InetAddress.getByName(GROUP_IP)
            multicastSocket.joinGroup(inetAddress)
            val receiveBuffer = ByteArray(1024)
            val receivePacket = DatagramPacket(receiveBuffer, receiveBuffer.size)
            multicastSocket.receive(receivePacket)//io阻塞
            val message = String(receivePacket.data, 0, receivePacket.length)
//            val hostIp = inetAddress.hostAddress
            back(message)
        } catch (e: Exception) {
            back(null)
            LogUtil.e("groupReceive error:${e.message}")
        }
    }

}